#include <iostream>
#include <algorithm>

#include <biosignal.h>

using namespace std;
using namespace biosignal;

template<class T>

class PrintCaller {
public:
    explicit PrintCaller(T *f) : printer(f) {}

    template<class SI>
    void operator()(const SI& sc) {
        printer->print(sc);
    }
private:
    T * printer;
};

class FrameIterationTest {
public:
    FrameIterationTest() : signals(0) {}
    int signals;
    void run() {

        cout << "creating biosignal " << endl;

        const BioSignal* bs = biosignal::load("/home/zaca/Development/test/crisis-generada.edf");
        cout << "created biosignal " << endl;

        cout << "bs:  " << bs << endl;
        bs->show_header_info( cout );

        cout << " === signal information==" << endl;
        for_each( bs->signals_group().begin() , bs->signals_group().end(),
                  PrintCaller<FrameIterationTest>(this) );


        cout << " === signal information end ==" << endl;

        cout << " === signal data ==" << endl;
        SignalSlice slice = bs->signal_slice(TimeOffset::Seconds(1), TimeOffset::Seconds(1.5));

        for_each( slice.begin() , slice.end(),
                  PrintCaller<FrameIterationTest>(this) );

//
//		DataFrameIterator dfi;
//		for(dfi = slice.begin(); dfi != slice.end(); ++dfi){
//			*dfi;
//			DataFrame::const_iterator si;
//			for (si = dfi->begin(); si != dfi->end(); ++si) {
//				montage::ChannelDataIterator di;
//				double val;
//				for (di = (*si)->begin(); di != (*si)->end(); ++di) {
//					val = *di;
//					cout.width(8);
//					cout << val << " | ";
//				}
//				cout << endl;
//			}
//			cout << "---------------" << endl;
//		}
//		cout << " === signal data ==" << endl;

        delete bs;
    }

    void print(const SourceSignal::SourceSignal_sptr& signal_info) {
        cout << " signal : " << signal_info->label() << " type : " << signal_info->type() << " signal_nr : " << ++signals << endl;
    }

    void print(shared_ptr<DataFrame> df) {
        cout << " time : " << df->time_period() << " signals : " << df->signal_source_data().size() << endl;
        for_each(df->begin(), df->end(), PrintCaller<FrameIterationTest>(this) );
    }

    void print(const shared_ptr<montage::ChannelData> & sd) {
//		cout << " data : " << sd->signal_info().lock()->label() << "  : " ;
        //for_each(sd.begin(), sd.end(), PrintCaller<FrameIterationTest>(this) );
        montage::ChannelDataIterator it = sd->begin();
        for (int i=0; i< 15; i++) {
            cout.width(8);
            cout << *it << " | " ;
            it++;
        }
        cout << endl;
    }
    void print(const double& sd) {
        cout << sd << " | ";
    }

};

int main() {
    FrameIterationTest test;
    test.run();
}
